/****************************************************************************
 * Copyright (C) 2009 SciTouch LLC
 * 
 * This file is part of Indigo toolkit.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

#include "molecule/molecule_hash.h"
#include "molecule/molecule.h"
#include "base_cpp/array.h"

dword MoleculeHash::calculate (const Molecule &mol)
{
   QS_DEF(Array<dword>, codes);
   QS_DEF(Array<dword>, oldcodes);
   int i, j, k;

   codes.clear_resize(mol.vertexEnd());

   for (i = mol.vertexBegin(); i != mol.vertexEnd(); i = mol.vertexNext(i))
   {
      int label = mol.getAtom(i).label;

      if (label != ELEM_H)
         codes[i] = (dword)label;
   }

   for (k = 0; k < 2; k++)
   {
      oldcodes.copy(codes);
      for (i = mol.vertexBegin(); i != mol.vertexEnd(); i = mol.vertexNext(i))
      {
         const Vertex &vertex = mol.getVertex(i);

         if (mol.getAtom(i).label == ELEM_H)
            continue;

         for (j = vertex.neiBegin(); j != vertex.neiEnd(); j = vertex.neiNext(j))
         {
            int nei = vertex.neiVertex(j);

            if (mol.getAtom(nei).label == ELEM_H)
               continue;

            codes[i] += oldcodes[nei] * oldcodes[nei];
         }
      }
   }

   dword res = 0;

   for (i = mol.vertexBegin(); i != mol.vertexEnd(); i = mol.vertexNext(i))
      if (mol.getAtom(i).label != ELEM_H)
         res += (codes[i] * codes[i]);

   return res;
}
